#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
学生信息管理系统
功能：针对txt文件的增删改查操作
"""

import os
import random
import sys
import hashlib
from typing import List, Dict, Optional

# 尝试导入matplotlib，如果失败则禁用图表功能
try:
    import matplotlib.pyplot as plt
    import matplotlib
    # 设置中文字体支持
    matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
    matplotlib.rcParams['axes.unicode_minus'] = False
    MATPLOTLIB_AVAILABLE = True
except ImportError:
    print("警告: matplotlib未安装，图表功能将被禁用")
    MATPLOTLIB_AVAILABLE = False

# 尝试导入pandas，如果失败则使用基础功能
try:
    import pandas as pd
    PANDAS_AVAILABLE = True
except ImportError:
    print("警告: pandas未安装，Excel/CSV导入导出功能将被禁用")
    PANDAS_AVAILABLE = False

# 尝试导入openpyxl，如果失败则禁用Excel功能
try:
    import openpyxl
    from openpyxl import Workbook
    from openpyxl.styles import Font, Alignment, PatternFill
    OPENPYXL_AVAILABLE = True
except ImportError:
    print("警告: openpyxl未安装，Excel功能将被禁用")
    OPENPYXL_AVAILABLE = False

class Course:
    """课程信息类"""
    def __init__(self, course_id: str, course_name: str, credits: float, teacher: str = ""):
        self.course_id = course_id
        self.course_name = course_name
        self.credits = credits
        self.teacher = teacher
    
    def to_string(self) -> str:
        """将课程信息转换为字符串格式"""
        return f"{self.course_id},{self.course_name},{self.credits},{self.teacher}"
    
    @classmethod
    def from_string(cls, line: str) -> 'Course':
        """从字符串创建课程对象"""
        parts = line.strip().split(',')
        if len(parts) != 4:
            raise ValueError("课程数据格式错误")
        return cls(parts[0], parts[1], float(parts[2]), parts[3])
    
    def __str__(self):
        return f"课程代码: {self.course_id}, 课程名称: {self.course_name}, 学分: {self.credits}, 授课教师: {self.teacher}"

class Grade:
    """成绩信息类"""
    def __init__(self, student_id: str, course_id: str, score: float, semester: str, exam_type: str = "期末考试"):
        self.student_id = student_id
        self.course_id = course_id
        self.score = score
        self.semester = semester  # 学期，如：2024-1
        self.exam_type = exam_type  # 考试类型：期末考试、期中考试、平时成绩等
    
    def to_string(self) -> str:
        """将成绩信息转换为字符串格式"""
        return f"{self.student_id},{self.course_id},{self.score},{self.semester},{self.exam_type}"
    
    @classmethod
    def from_string(cls, line: str) -> 'Grade':
        """从字符串创建成绩对象"""
        parts = line.strip().split(',')
        if len(parts) != 5:
            raise ValueError("成绩数据格式错误")
        return cls(parts[0], parts[1], float(parts[2]), parts[3], parts[4])
    
    def get_grade_point(self) -> float:
        """根据分数计算绩点"""
        if self.score >= 90:
            return 4.0
        elif self.score >= 85:
            return 3.7
        elif self.score >= 82:
            return 3.3
        elif self.score >= 78:
            return 3.0
        elif self.score >= 75:
            return 2.7
        elif self.score >= 72:
            return 2.3
        elif self.score >= 68:
            return 2.0
        elif self.score >= 64:
            return 1.5
        elif self.score >= 60:
            return 1.0
        else:
            return 0.0
    
    def get_letter_grade(self) -> str:
        """根据分数获取等级"""
        if self.score >= 90:
            return "A"
        elif self.score >= 80:
            return "B"
        elif self.score >= 70:
            return "C"
        elif self.score >= 60:
            return "D"
        else:
            return "F"
    
    def __str__(self):
        return f"学号: {self.student_id}, 课程: {self.course_id}, 成绩: {self.score}, 学期: {self.semester}, 类型: {self.exam_type}"

class Student:
    """学生信息类"""
    def __init__(self, student_id: str, name: str, age: int, major: str, class_name: str):
        self.student_id = student_id
        self.name = name
        self.age = age
        self.major = major
        self.class_name = class_name

    def to_string(self) -> str:
        """将学生信息转换为字符串格式"""
        return f"{self.student_id},{self.name},{self.age},{self.major},{self.class_name}"

    @classmethod
    def from_string(cls, line: str) -> 'Student':
        """从字符串创建学生对象"""
        parts = line.strip().split(',')
        if len(parts) != 5:
            raise ValueError("数据格式错误")
        return cls(parts[0], parts[1], int(parts[2]), parts[3], parts[4])

    def __str__(self):
        return f"学号: {self.student_id}, 姓名: {self.name}, 年龄: {self.age}, 专业: {self.major}, 班级: {self.class_name}"

class User:
    """用户类"""
    def __init__(self, username: str, password_hash: str, role: str, student_id: str = ""):
        self.username = username
        self.password_hash = password_hash
        self.role = role  # admin, teacher, student
        self.student_id = student_id  # 如果是学生角色，对应的学号

    def to_string(self) -> str:
        """将用户信息转换为字符串格式"""
        return f"{self.username},{self.password_hash},{self.role},{self.student_id}"

    @classmethod
    def from_string(cls, line: str) -> 'User':
        """从字符串创建用户对象"""
        parts = line.strip().split(',')
        if len(parts) != 4:
            raise ValueError("用户数据格式错误")
        return cls(parts[0], parts[1], parts[2], parts[3])

    def __str__(self):
        return f"用户名: {self.username}, 角色: {self.role}, 对应学号: {self.student_id}"

    @staticmethod
    def hash_password(password: str) -> str:
        """对密码进行哈希处理"""
        return hashlib.sha256(password.encode()).hexdigest()

    @staticmethod
    def verify_password(password: str, password_hash: str) -> bool:
        """验证密码"""
        return User.hash_password(password) == password_hash

class StudentManagementSystem:
    """学生信息管理系统"""
    
    def __init__(self, data_file: str = "students.txt"):
        self.data_file = data_file
        self.students: List[Student] = []
        self.courses: List[Course] = []
        self.grades: List[Grade] = []
        self.users: List[User] = []
        self.courses_file = "courses.txt"
        self.grades_file = "grades.txt"
        self.users_file = "users.txt"
        self.current_user: Optional[User] = None  # 当前登录用户
        self.load_data()
        self.load_courses()
        self.load_grades()
        self.load_users()
    
    def load_data(self):
        """从文件加载学生数据"""
        if os.path.exists(self.data_file):
            try:
                with open(self.data_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        if line.strip():
                            try:
                                student = Student.from_string(line)
                                self.students.append(student)
                            except ValueError as e:
                                print(f"警告：跳过格式错误的行: {line.strip()}, 错误: {e}")
            except Exception as e:
                print(f"加载数据时出错: {e}")
        else:
            print(f"数据文件 {self.data_file} 不存在，将创建新文件")
    
    def load_courses(self):
        """从文件加载课程数据"""
        if os.path.exists(self.courses_file):
            try:
                with open(self.courses_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        if line.strip():
                            try:
                                course = Course.from_string(line)
                                self.courses.append(course)
                            except ValueError as e:
                                print(f"警告：跳过格式错误的课程行: {line.strip()}, 错误: {e}")
            except Exception as e:
                print(f"加载课程数据时出错: {e}")
        else:
            print(f"课程文件 {self.courses_file} 不存在，将创建新文件")
    
    def load_grades(self):
        """从文件加载成绩数据"""
        if os.path.exists(self.grades_file):
            try:
                with open(self.grades_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        if line.strip():
                            try:
                                grade = Grade.from_string(line)
                                self.grades.append(grade)
                            except ValueError as e:
                                print(f"警告：跳过格式错误的成绩行: {line.strip()}, 错误: {e}")
            except Exception as e:
                print(f"加载成绩数据时出错: {e}")
        else:
            print(f"成绩文件 {self.grades_file} 不存在，将创建新文件")
    
    def save_data(self):
        """保存学生数据到文件"""
        try:
            with open(self.data_file, 'w', encoding='utf-8') as f:
                for student in self.students:
                    f.write(student.to_string() + '\n')
            print("数据保存成功！")
        except Exception as e:
            print(f"保存数据时出错: {e}")
    
    def save_courses(self):
        """保存课程数据到文件"""
        try:
            with open(self.courses_file, 'w', encoding='utf-8') as f:
                for course in self.courses:
                    f.write(course.to_string() + '\n')
            print("课程数据保存成功！")
        except Exception as e:
            print(f"保存课程数据时出错: {e}")
    
    def save_grades(self):
        """保存成绩数据到文件"""
        try:
            with open(self.grades_file, 'w', encoding='utf-8') as f:
                for grade in self.grades:
                    f.write(grade.to_string() + '\n')
            print("成绩数据保存成功！")
        except Exception as e:
            print(f"保存成绩数据时出错: {e}")

    def load_users(self):
        """从文件加载用户数据"""
        if os.path.exists(self.users_file):
            try:
                with open(self.users_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        if line.strip():
                            try:
                                user = User.from_string(line)
                                self.users.append(user)
                            except ValueError as e:
                                print(f"警告：跳过格式错误的行: {line.strip()}, 错误: {e}")
            except Exception as e:
                print(f"加载用户数据时出错: {e}")
        else:
            print(f"用户文件 {self.users_file} 不存在，将创建新文件")

    def save_users(self):
        """保存用户数据到文件"""
        try:
            with open(self.users_file, 'w', encoding='utf-8') as f:
                for user in self.users:
                    f.write(user.to_string() + '\n')
            print("用户数据保存成功！")
        except Exception as e:
            print(f"保存用户数据时出错: {e}")

    def login(self):
        """用户登录"""
        print("\n=== 用户登录 ===")
        username = input("请输入用户名: ").strip()
        if not username:
            print("用户名不能为空！")
            return False

        password = input("请输入密码: ").strip()
        if not password:
            print("密码不能为空！")
            return False

        # 查找用户
        for user in self.users:
            if user.username == username and User.verify_password(password, user.password_hash):
                self.current_user = user
                print(f"登录成功！欢迎 {user.username} ({user.role})")
                return True

        print("用户名或密码错误！")
        return False

    def logout(self):
        """用户登出"""
        if self.current_user:
            print(f"用户 {self.current_user.username} 已登出")
            self.current_user = None
        else:
            print("当前没有用户登录")

    def require_permission(self, required_role: str):
        """权限检查装饰器"""
        def decorator(func):
            def wrapper(*args, **kwargs):
                if not self.current_user:
                    print("请先登录！")
                    return
                if self.current_user.role not in ['admin', required_role]:
                    print(f"权限不足！需要 {required_role} 或 admin 权限")
                    return
                return func(*args, **kwargs)
            return wrapper
        return decorator

    def get_current_user_info(self):
        """获取当前用户信息"""
        if self.current_user:
            return f"当前用户: {self.current_user.username} (角色: {self.current_user.role})"
        return "未登录"

    def user_management_menu(self):
        """用户管理菜单（仅管理员可用）"""
        print("\n=== 用户管理 ===")
        print("1. 添加用户")
        print("2. 删除用户")
        print("3. 修改用户")
        print("4. 查询用户")
        print("5. 显示所有用户")
        print("6. 返回主菜单")

        choice = input("请选择操作 (1-6): ").strip()

        if choice == '1':
            self.add_user()
        elif choice == '2':
            self.delete_user()
        elif choice == '3':
            self.update_user()
        elif choice == '4':
            self.query_user()
        elif choice == '5':
            self.display_all_users()
        elif choice == '6':
            return
        else:
            print("无效选择！")

    def add_user(self):
        """添加用户"""
        print("\n=== 添加用户 ===")
        username = input("请输入用户名: ").strip()
        if not username:
            print("用户名不能为空！")
            return

        # 检查用户名是否已存在
        if any(u.username == username for u in self.users):
            print("该用户名已存在！")
            return

        password = input("请输入密码: ").strip()
        if not password:
            print("密码不能为空！")
            return

        role = input("请输入角色 (admin/teacher/student): ").strip().lower()
        if role not in ['admin', 'teacher', 'student']:
            print("角色必须是 admin、teacher 或 student！")
            return

        student_id = ""
        if role == 'student':
            student_id = input("请输入对应学号: ").strip()
            if not student_id:
                print("学生角色必须提供学号！")
                return
            # 验证学号是否存在
            if not any(s.student_id == student_id for s in self.students):
                print("该学号不存在！")
                return

        user = User(username, User.hash_password(password), role, student_id)
        self.users.append(user)
        self.save_users()
        print("用户添加成功！")

    def delete_user(self):
        """删除用户"""
        print("\n=== 删除用户 ===")
        username = input("请输入要删除的用户名: ").strip()

        if not username:
            print("用户名不能为空！")
            return

        # 不能删除自己
        if self.current_user and self.current_user.username == username:
            print("不能删除当前登录用户！")
            return

        # 查找用户
        for i, user in enumerate(self.users):
            if user.username == username:
                print(f"找到用户: {user}")
                confirm = input("确认删除？(y/n): ").strip().lower()
                if confirm == 'y':
                    del self.users[i]
                    self.save_users()
                    print("用户删除成功！")
                else:
                    print("取消删除操作")
                return

        print("未找到该用户！")

    def update_user(self):
        """修改用户"""
        print("\n=== 修改用户 ===")
        username = input("请输入要修改的用户名: ").strip()

        if not username:
            print("用户名不能为空！")
            return

        # 查找用户
        for user in self.users:
            if user.username == username:
                print(f"当前用户信息: {user}")
                print("请输入新的信息（直接回车保持原值）:")

                new_password = input("新密码（留空保持不变）: ").strip()
                if new_password:
                    user.password_hash = User.hash_password(new_password)

                new_role = input(f"角色 [{user.role}]: ").strip().lower()
                if new_role and new_role in ['admin', 'teacher', 'student']:
                    user.role = new_role
                elif new_role:
                    print("角色必须是 admin、teacher 或 student，保持原值")

                new_student_id = input(f"对应学号 [{user.student_id}]: ").strip()
                if new_student_id or (user.role == 'student' and not user.student_id):
                    if user.role == 'student':
                        # 验证学号是否存在
                        if any(s.student_id == new_student_id for s in self.students):
                            user.student_id = new_student_id
                        else:
                            print("该学号不存在，保持原值")
                    else:
                        user.student_id = new_student_id

                self.save_users()
                print("用户信息修改成功！")
                print(f"修改后信息: {user}")
                return

        print("未找到该用户！")

    def query_user(self):
        """查询用户"""
        print("\n=== 查询用户 ===")
        username = input("请输入用户名: ").strip()

        if not username:
            print("用户名不能为空！")
            return

        for user in self.users:
            if user.username == username:
                print("查询结果:")
                print(user)
                return

        print("未找到该用户！")

    def display_all_users(self):
        """显示所有用户"""
        print("\n=== 所有用户信息 ===")
        if not self.users:
            print("暂无用户信息！")
            return

        print(f"共有 {len(self.users)} 个用户：")
        print("-" * 60)
        print(f"{'用户名':<15} {'角色':<10} {'对应学号':<15}")
        print("-" * 60)

        for user in self.users:
            print(f"{user.username:<15} {user.role:<10} {user.student_id:<15}")

        print("-" * 60)

    def view_personal_info(self):
        """查看个人信息（学生专用）"""
        if not self.current_user or self.current_user.role != 'student':
            print("权限不足！")
            return

        student_id = self.current_user.student_id
        for student in self.students:
            if student.student_id == student_id:
                print("\n=== 个人信息 ===")
                print(f"学号: {student.student_id}")
                print(f"姓名: {student.name}")
                print(f"年龄: {student.age}")
                print(f"专业: {student.major}")
                print(f"班级: {student.class_name}")
                return

        print("未找到个人信息！")
    
    def add_student(self):
        """添加学生信息"""
        print("\n=== 添加学生信息 ===")
        try:
            student_id = input("请输入学号: ").strip()
            if not student_id:
                print("学号不能为空！")
                return
            
            # 验证学号格式（8位数字）
            if not self.validate_student_id(student_id):
                print("学号格式错误！请输入8位数字（如：20240001）")
                return
            
            # 检查学号是否已存在
            if any(s.student_id == student_id for s in self.students):
                print("该学号已存在！")
                return
            
            name = input("请输入姓名: ").strip()
            if not name:
                print("姓名不能为空！")
                return
            
            # 验证姓名格式
            if not self.validate_name(name):
                print("姓名格式错误！请输入2-10个中文字符")
                return
            
            age = int(input("请输入年龄: "))
            if not self.validate_age(age):
                print("年龄必须在16-30岁之间！")
                return
            
            major = input("请输入专业: ").strip()
            if not major:
                print("专业不能为空！")
                return
            
            # 验证专业格式
            if not self.validate_major(major):
                print("专业格式错误！请输入2-20个字符")
                return
            
            class_name = input("请输入班级: ").strip()
            if not class_name:
                print("班级不能为空！")
                return
            
            # 验证班级格式
            if not self.validate_class_name(class_name):
                print("班级格式错误！请输入有效的班级名称")
                return
            
            student = Student(student_id, name, age, major, class_name)
            self.students.append(student)
            self.save_data()
            print("学生信息添加成功！")
            
        except ValueError:
            print("输入格式错误，请重新输入！")
        except Exception as e:
            print(f"添加学生时出错: {e}")
    
    def validate_student_id(self, student_id):
        """验证学号格式"""
        return 6 <= len(student_id) <= 10 and student_id.isdigit()
    
    def validate_name(self, name):
        """验证姓名格式"""
        return 2 <= len(name) <= 10 and all('\u4e00' <= char <= '\u9fff' for char in name)
    
    def validate_age(self, age):
        """验证年龄范围"""
        return 16 <= age <= 50
    
    def validate_major(self, major):
        """验证专业格式"""
        return 2 <= len(major) <= 20
    
    def validate_class_name(self, class_name):
        """验证班级格式"""
        return 3 <= len(class_name) <= 15
    
    def delete_student(self):
        """删除学生信息"""
        print("\n=== 删除学生信息 ===")
        student_id = input("请输入要删除的学生学号: ").strip()
        
        if not student_id:
            print("学号不能为空！")
            return
        
        # 查找学生
        for i, student in enumerate(self.students):
            if student.student_id == student_id:
                print(f"找到学生: {student}")
                confirm = input("确认删除？(y/n): ").strip().lower()
                if confirm == 'y':
                    del self.students[i]
                    self.save_data()
                    print("学生信息删除成功！")
                else:
                    print("取消删除操作")
                return
        
        print("未找到该学号的学生！")
    
    def update_student(self):
        """修改学生信息"""
        print("\n=== 修改学生信息 ===")
        student_id = input("请输入要修改的学生学号: ").strip()
        
        if not student_id:
            print("学号不能为空！")
            return
        
        # 查找学生
        for student in self.students:
            if student.student_id == student_id:
                print(f"当前学生信息: {student}")
                print("请输入新的信息（直接回车保持原值）:")
                
                try:
                    new_name = input(f"姓名 [{student.name}]: ").strip()
                    if new_name:
                        student.name = new_name
                    
                    new_age = input(f"年龄 [{student.age}]: ").strip()
                    if new_age:
                        age = int(new_age)
                        if age > 0:
                            student.age = age
                        else:
                            print("年龄必须大于0，保持原值")
                    
                    new_major = input(f"专业 [{student.major}]: ").strip()
                    if new_major:
                        student.major = new_major
                    
                    new_class = input(f"班级 [{student.class_name}]: ").strip()
                    if new_class:
                        student.class_name = new_class
                    
                    self.save_data()
                    print("学生信息修改成功！")
                    print(f"修改后信息: {student}")
                except ValueError:
                    print("输入格式错误，修改失败！")
                return
        
        print("未找到该学号的学生！")
    
    def query_students(self):
        """查询学生信息"""
        print("\n=== 查询学生信息 ===")
        print("1. 查询所有学生")
        print("2. 按学号查询")
        print("3. 按姓名查询")
        print("4. 按专业查询")
        print("5. 按班级查询")
        
        choice = input("请选择查询方式 (1-5): ").strip()
        
        if choice == '1':
            self.query_all_students()
        elif choice == '2':
            self.query_by_id()
        elif choice == '3':
            self.query_by_name()
        elif choice == '4':
            self.query_by_major()
        elif choice == '5':
            self.query_by_class()
        else:
            print("无效选择！")
    
    def query_all_students(self):
        """查询所有学生"""
        if not self.students:
            print("暂无学生信息！")
            return
        
        print(f"\n共有 {len(self.students)} 名学生：")
        self.display_students_table(self.students)
    
    def query_by_id(self):
        """按学号查询"""
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        for student in self.students:
            if student.student_id == student_id:
                print("查询结果:")
                self.display_students_table([student])
                return
        
        print("未找到该学号的学生！")
    
    def query_by_name(self):
        """按姓名查询"""
        name = input("请输入姓名（支持模糊查询）: ").strip()
        if not name:
            print("姓名不能为空！")
            return
        
        results = [s for s in self.students if name in s.name]
        if results:
            print(f"找到 {len(results)} 名匹配的学生：")
            self.display_students_table(results)
        else:
            print("未找到匹配的学生！")
    
    def query_by_major(self):
        """按专业查询"""
        major = input("请输入专业（支持模糊查询）: ").strip()
        if not major:
            print("专业不能为空！")
            return
        
        results = [s for s in self.students if major in s.major]
        if results:
            print(f"找到 {len(results)} 名匹配的学生：")
            self.display_students_table(results)
        else:
            print("未找到匹配的学生！")
    
    def query_by_class(self):
        """按班级查询"""
        class_name = input("请输入班级（支持模糊查询）: ").strip()
        if not class_name:
            print("班级不能为空！")
            return
        
        results = [s for s in self.students if class_name in s.class_name]
        if results:
            print(f"找到 {len(results)} 名匹配的学生：")
            self.display_students_table(results)
        else:
            print("未找到匹配的学生！")
    
    def display_students_table(self, students: List[Student]):
        """以表格形式显示学生信息"""
        if not students:
            print("暂无学生信息！")
            return
        
        # 计算各列的最大宽度
        max_id_len = max(len("学号"), max(len(s.student_id) for s in students))
        max_name_len = max(len("姓名"), max(len(s.name) for s in students))
        max_age_len = max(len("年龄"), max(len(str(s.age)) for s in students))
        max_major_len = max(len("专业"), max(len(s.major) for s in students))
        max_class_len = max(len("班级"), max(len(s.class_name) for s in students))
        
        # 设置最小宽度
        max_id_len = max(max_id_len, 8)
        max_name_len = max(max_name_len, 6)
        max_age_len = max(max_age_len, 4)
        max_major_len = max(max_major_len, 8)
        max_class_len = max(max_class_len, 8)
        
        # 创建表格边框
        def create_line():
            return "+" + "-" * (max_id_len + 2) + "+" + "-" * (max_name_len + 2) + "+" + "-" * (max_age_len + 2) + "+" + "-" * (max_major_len + 2) + "+" + "-" * (max_class_len + 2) + "+"
        
        def create_row(items):
            return "| " + f"{items[0]:<{max_id_len}} | {items[1]:<{max_name_len}} | {items[2]:<{max_age_len}} | {items[3]:<{max_major_len}} | {items[4]:<{max_class_len}} |"
        
        # 打印表头
        print(create_line())
        print(create_row(["学号", "姓名", "年龄", "专业", "班级"]))
        print(create_line())
        
        # 打印数据行
        for i, student in enumerate(students, 1):
            print(create_row([student.student_id, student.name, str(student.age), student.major, student.class_name]))
        
        print(create_line())
        print(f"共 {len(students)} 条记录")
    
    def statistics_menu(self):
        """数据统计分析菜单"""
        print("\n=== 数据统计分析 ===")
        print("1. 按专业统计学生人数")
        print("2. 按班级统计学生人数")
        print("3. 年龄分布统计")
        print("4. 平均年龄计算")
        print("5. 综合统计报告")
        print("6. 生成数据图表")
        print("7. 返回主菜单")
        
        choice = input("请选择统计方式 (1-7): ").strip()
        
        if choice == '1':
            self.statistics_by_major()
        elif choice == '2':
            self.statistics_by_class()
        elif choice == '3':
            self.statistics_by_age()
        elif choice == '4':
            self.calculate_average_age()
        elif choice == '5':
            self.comprehensive_report()
        elif choice == '6':
            self.chart_menu()
        elif choice == '7':
            return
        else:
            print("无效选择！")
    
    def statistics_by_major(self):
        """按专业统计学生人数"""
        print("\n=== 按专业统计学生人数 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        major_count = {}
        for student in self.students:
            major = student.major
            major_count[major] = major_count.get(major, 0) + 1
        
        # 按人数降序排序
        sorted_majors = sorted(major_count.items(), key=lambda x: x[1], reverse=True)
        
        print(f"\n专业统计结果（共 {len(sorted_majors)} 个专业）：")
        print("-" * 50)
        for i, (major, count) in enumerate(sorted_majors, 1):
            print(f"{i:2d}. {major:<20} : {count:3d} 人")
        
        print("-" * 50)
        print(f"总计: {len(self.students)} 人")
    
    def statistics_by_class(self):
        """按班级统计学生人数"""
        print("\n=== 按班级统计学生人数 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        class_count = {}
        for student in self.students:
            class_name = student.class_name
            class_count[class_name] = class_count.get(class_name, 0) + 1
        
        # 按班级名称排序
        sorted_classes = sorted(class_count.items())
        
        print(f"\n班级统计结果（共 {len(sorted_classes)} 个班级）：")
        print("-" * 50)
        for i, (class_name, count) in enumerate(sorted_classes, 1):
            print(f"{i:2d}. {class_name:<15} : {count:3d} 人")
        
        print("-" * 50)
        print(f"总计: {len(self.students)} 人")
    
    def statistics_by_age(self):
        """年龄分布统计"""
        print("\n=== 年龄分布统计 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        age_count = {}
        for student in self.students:
            age = student.age
            age_count[age] = age_count.get(age, 0) + 1
        
        # 按年龄排序
        sorted_ages = sorted(age_count.items())
        
        print(f"\n年龄分布统计：")
        print("-" * 30)
        for age, count in sorted_ages:
            print(f"年龄 {age:2d} 岁 : {count:3d} 人")
        
        print("-" * 30)
        print(f"总计: {len(self.students)} 人")
        
        # 年龄范围
        min_age = min(age_count.keys())
        max_age = max(age_count.keys())
        print(f"年龄范围: {min_age} - {max_age} 岁")
    
    def calculate_average_age(self):
        """计算平均年龄"""
        print("\n=== 平均年龄计算 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        total_age = sum(student.age for student in self.students)
        avg_age = total_age / len(self.students)
        
        print(f"学生总数: {len(self.students)} 人")
        print(f"年龄总和: {total_age} 岁")
        print(f"平均年龄: {avg_age:.2f} 岁")
        
        # 年龄中位数
        ages = sorted([student.age for student in self.students])
        n = len(ages)
        if n % 2 == 0:
            median_age = (ages[n//2-1] + ages[n//2]) / 2
        else:
            median_age = ages[n//2]
        
        print(f"年龄中位数: {median_age:.2f} 岁")
    
    def comprehensive_report(self):
        """综合统计报告"""
        print("\n=== 综合统计报告 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        print(f"报告生成时间: {self.get_current_time()}")
        print("=" * 60)
        
        # 基本统计
        print(f"学生总数: {len(self.students)} 人")
        
        # 年龄统计
        ages = [student.age for student in self.students]
        print(f"年龄范围: {min(ages)} - {max(ages)} 岁")
        print(f"平均年龄: {sum(ages)/len(ages):.2f} 岁")
        
        # 专业统计
        major_count = {}
        for student in self.students:
            major = student.major
            major_count[major] = major_count.get(major, 0) + 1
        
        print(f"\n专业分布（共 {len(major_count)} 个专业）:")
        for major, count in sorted(major_count.items(), key=lambda x: x[1], reverse=True):
            percentage = (count / len(self.students)) * 100
            print(f"  {major:<20} : {count:3d} 人 ({percentage:5.1f}%)")
        
        # 班级统计
        class_count = {}
        for student in self.students:
            class_name = student.class_name
            class_count[class_name] = class_count.get(class_name, 0) + 1
        
        print(f"\n班级分布（共 {len(class_count)} 个班级）:")
        for class_name, count in sorted(class_count.items()):
            percentage = (count / len(self.students)) * 100
            print(f"  {class_name:<15} : {count:3d} 人 ({percentage:5.1f}%)")
        
        print("=" * 60)
    
    def get_current_time(self):
        """获取当前时间"""
        import datetime
        return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    def advanced_query(self):
        """高级查询功能"""
        print("\n=== 高级查询 ===")
        print("1. 多条件组合查询")
        print("2. 年龄范围查询")
        print("3. 按入学年份查询")
        print("4. 返回主菜单")
        
        choice = input("请选择查询方式 (1-4): ").strip()
        
        if choice == '1':
            self.multi_condition_query()
        elif choice == '2':
            self.age_range_query()
        elif choice == '3':
            self.year_query()
        elif choice == '4':
            return
        else:
            print("无效选择！")
    
    def multi_condition_query(self):
        """多条件组合查询"""
        print("\n=== 多条件组合查询 ===")
        print("请输入查询条件（直接回车跳过该条件）:")
        
        # 专业条件
        major = input("专业（支持模糊查询）: ").strip()
        
        # 班级条件
        class_name = input("班级（支持模糊查询）: ").strip()
        
        # 年龄范围
        min_age = input("最小年龄: ").strip()
        max_age = input("最大年龄: ").strip()
        
        # 姓名条件
        name = input("姓名（支持模糊查询）: ").strip()
        
        # 执行查询
        results = self.students.copy()
        
        if major:
            results = [s for s in results if major in s.major]
        
        if class_name:
            results = [s for s in results if class_name in s.class_name]
        
        if min_age:
            try:
                min_age = int(min_age)
                results = [s for s in results if s.age >= min_age]
            except ValueError:
                print("最小年龄格式错误，忽略该条件")
        
        if max_age:
            try:
                max_age = int(max_age)
                results = [s for s in results if s.age <= max_age]
            except ValueError:
                print("最大年龄格式错误，忽略该条件")
        
        if name:
            results = [s for s in results if name in s.name]
        
        # 显示结果
        if results:
            print(f"\n找到 {len(results)} 名匹配的学生：")
            self.display_students_table(results)
        else:
            print("未找到匹配的学生！")
    
    def age_range_query(self):
        """年龄范围查询"""
        print("\n=== 年龄范围查询 ===")
        try:
            min_age = int(input("请输入最小年龄: ").strip())
            max_age = int(input("请输入最大年龄: ").strip())
            
            if min_age > max_age:
                print("最小年龄不能大于最大年龄！")
                return
            
            results = [s for s in self.students if min_age <= s.age <= max_age]
            
            if results:
                print(f"\n年龄在 {min_age}-{max_age} 岁之间的学生（共 {len(results)} 人）:")
                self.display_students_table(results)
            else:
                print("未找到符合年龄范围的学生！")
                
        except ValueError:
            print("年龄格式错误，请输入数字！")
    
    def year_query(self):
        """按入学年份查询"""
        print("\n=== 按入学年份查询 ===")
        year = input("请输入入学年份（如：2024）: ").strip()
        
        if not year:
            print("年份不能为空！")
            return
        
        # 根据学号前4位判断入学年份
        results = [s for s in self.students if s.student_id.startswith(year)]
        
        if results:
            print(f"\n{year}年入学的学生（共 {len(results)} 人）:")
            self.display_students_table(results)
        else:
            print(f"未找到 {year}年入学的学生！")
    
    def chart_menu(self):
        """图表生成菜单"""
        if not MATPLOTLIB_AVAILABLE:
            print("\n=== 生成数据图表 ===")
            print("❌ 图表功能不可用！")
            print("请安装matplotlib库: pip install matplotlib")
            return
        
        print("\n=== 生成数据图表 ===")
        print("1. 专业分布柱状图")
        print("2. 班级分布柱状图")
        print("3. 年龄分布折线图")
        print("4. 年龄分布柱状图")
        print("5. 综合统计图表")
        print("6. 返回统计菜单")
        
        choice = input("请选择图表类型 (1-6): ").strip()
        
        if choice == '1':
            self.create_major_bar_chart()
        elif choice == '2':
            self.create_class_bar_chart()
        elif choice == '3':
            self.create_age_line_chart()
        elif choice == '4':
            self.create_age_bar_chart()
        elif choice == '5':
            self.create_comprehensive_charts()
        elif choice == '6':
            return
        else:
            print("无效选择！")
    
    def create_major_bar_chart(self):
        """创建专业分布柱状图"""
        print("\n=== 生成专业分布柱状图 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        # 统计专业数据
        major_count = {}
        for student in self.students:
            major = student.major
            major_count[major] = major_count.get(major, 0) + 1
        
        # 按人数降序排序
        sorted_majors = sorted(major_count.items(), key=lambda x: x[1], reverse=True)
        
        majors = [item[0] for item in sorted_majors]
        counts = [item[1] for item in sorted_majors]
        
        # 创建图表
        plt.figure(figsize=(12, 8))
        bars = plt.bar(range(len(majors)), counts, color='skyblue', edgecolor='navy', alpha=0.7)
        
        # 设置标题和标签
        plt.title('专业分布统计', fontsize=16, fontweight='bold')
        plt.xlabel('专业', fontsize=12)
        plt.ylabel('学生人数', fontsize=12)
        
        # 设置x轴标签
        plt.xticks(range(len(majors)), majors, rotation=45, ha='right')
        
        # 在柱子上显示数值
        for i, bar in enumerate(bars):
            height = bar.get_height()
            plt.text(bar.get_x() + bar.get_width()/2., height + 0.1,
                    f'{int(height)}', ha='center', va='bottom')
        
        # 调整布局
        plt.tight_layout()
        
        # 保存图表
        filename = '专业分布统计.png'
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
        
        # 显示图表
        plt.show()
    
    def create_class_bar_chart(self):
        """创建班级分布柱状图"""
        print("\n=== 生成班级分布柱状图 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        # 统计班级数据
        class_count = {}
        for student in self.students:
            class_name = student.class_name
            class_count[class_name] = class_count.get(class_name, 0) + 1
        
        # 按班级名称排序
        sorted_classes = sorted(class_count.items())
        
        classes = [item[0] for item in sorted_classes]
        counts = [item[1] for item in sorted_classes]
        
        # 创建图表
        plt.figure(figsize=(14, 8))
        bars = plt.bar(range(len(classes)), counts, color='lightcoral', edgecolor='darkred', alpha=0.7)
        
        # 设置标题和标签
        plt.title('班级分布统计', fontsize=16, fontweight='bold')
        plt.xlabel('班级', fontsize=12)
        plt.ylabel('学生人数', fontsize=12)
        
        # 设置x轴标签
        plt.xticks(range(len(classes)), classes, rotation=45, ha='right')
        
        # 在柱子上显示数值
        for i, bar in enumerate(bars):
            height = bar.get_height()
            plt.text(bar.get_x() + bar.get_width()/2., height + 0.1,
                    f'{int(height)}', ha='center', va='bottom')
        
        # 调整布局
        plt.tight_layout()
        
        # 保存图表
        filename = '班级分布统计.png'
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
        
        # 显示图表
        plt.show()
    
    def create_age_line_chart(self):
        """创建年龄分布折线图"""
        print("\n=== 生成年龄分布折线图 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        # 统计年龄数据
        age_count = {}
        for student in self.students:
            age = student.age
            age_count[age] = age_count.get(age, 0) + 1
        
        # 按年龄排序
        sorted_ages = sorted(age_count.items())
        
        ages = [item[0] for item in sorted_ages]
        counts = [item[1] for item in sorted_ages]
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        plt.plot(ages, counts, marker='o', linewidth=2, markersize=8, color='green', markerfacecolor='lightgreen')
        
        # 设置标题和标签
        plt.title('年龄分布折线图', fontsize=16, fontweight='bold')
        plt.xlabel('年龄', fontsize=12)
        plt.ylabel('学生人数', fontsize=12)
        
        # 设置网格
        plt.grid(True, alpha=0.3)
        
        # 在点上显示数值
        for i, (age, count) in enumerate(zip(ages, counts)):
            plt.annotate(f'{count}', (age, count), textcoords="offset points", xytext=(0,10), ha='center')
        
        # 调整布局
        plt.tight_layout()
        
        # 保存图表
        filename = '年龄分布折线图.png'
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
        
        # 显示图表
        plt.show()
    
    def create_age_bar_chart(self):
        """创建年龄分布柱状图"""
        print("\n=== 生成年龄分布柱状图 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        # 统计年龄数据
        age_count = {}
        for student in self.students:
            age = student.age
            age_count[age] = age_count.get(age, 0) + 1
        
        # 按年龄排序
        sorted_ages = sorted(age_count.items())
        
        ages = [item[0] for item in sorted_ages]
        counts = [item[1] for item in sorted_ages]
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        bars = plt.bar(ages, counts, color='orange', edgecolor='darkorange', alpha=0.7)
        
        # 设置标题和标签
        plt.title('年龄分布柱状图', fontsize=16, fontweight='bold')
        plt.xlabel('年龄', fontsize=12)
        plt.ylabel('学生人数', fontsize=12)
        
        # 在柱子上显示数值
        for bar in bars:
            height = bar.get_height()
            plt.text(bar.get_x() + bar.get_width()/2., height + 0.1,
                    f'{int(height)}', ha='center', va='bottom')
        
        # 调整布局
        plt.tight_layout()
        
        # 保存图表
        filename = '年龄分布柱状图.png'
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"图表已保存为: {filename}")
        
        # 显示图表
        plt.show()
    
    def create_comprehensive_charts(self):
        """创建综合统计图表"""
        print("\n=== 生成综合统计图表 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        # 创建子图
        fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12))
        
        # 1. 专业分布饼图
        major_count = {}
        for student in self.students:
            major = student.major
            major_count[major] = major_count.get(major, 0) + 1
        
        majors = list(major_count.keys())
        counts = list(major_count.values())
        colors = plt.cm.Set3(range(len(majors)))
        
        ax1.pie(counts, labels=majors, autopct='%1.1f%%', colors=colors, startangle=90)
        ax1.set_title('专业分布饼图', fontsize=14, fontweight='bold')
        
        # 2. 年龄分布柱状图
        age_count = {}
        for student in self.students:
            age = student.age
            age_count[age] = age_count.get(age, 0) + 1
        
        sorted_ages = sorted(age_count.items())
        ages = [item[0] for item in sorted_ages]
        age_counts = [item[1] for item in sorted_ages]
        
        ax2.bar(ages, age_counts, color='lightblue', edgecolor='navy', alpha=0.7)
        ax2.set_title('年龄分布柱状图', fontsize=14, fontweight='bold')
        ax2.set_xlabel('年龄')
        ax2.set_ylabel('学生人数')
        
        # 3. 班级分布柱状图（前10个班级）
        class_count = {}
        for student in self.students:
            class_name = student.class_name
            class_count[class_name] = class_count.get(class_name, 0) + 1
        
        sorted_classes = sorted(class_count.items(), key=lambda x: x[1], reverse=True)[:10]
        classes = [item[0] for item in sorted_classes]
        class_counts = [item[1] for item in sorted_classes]
        
        ax3.bar(range(len(classes)), class_counts, color='lightgreen', edgecolor='darkgreen', alpha=0.7)
        ax3.set_title('班级分布柱状图（前10个）', fontsize=14, fontweight='bold')
        ax3.set_xlabel('班级')
        ax3.set_ylabel('学生人数')
        ax3.set_xticks(range(len(classes)))
        ax3.set_xticklabels(classes, rotation=45, ha='right')
        
        # 4. 年龄趋势折线图
        ax4.plot(ages, age_counts, marker='o', linewidth=2, markersize=6, color='red')
        ax4.set_title('年龄分布趋势图', fontsize=14, fontweight='bold')
        ax4.set_xlabel('年龄')
        ax4.set_ylabel('学生人数')
        ax4.grid(True, alpha=0.3)
        
        # 调整布局
        plt.tight_layout()
        
        # 保存图表
        filename = '综合统计图表.png'
        plt.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"综合图表已保存为: {filename}")
        
        # 显示图表
        plt.show()
    
    def import_export_menu(self):
        """数据导入导出菜单"""
        print("\n=== 数据导入导出 ===")
        print("1. 导出到Excel文件")
        print("2. 从Excel文件导入")
        print("3. 导出到CSV文件")
        print("4. 从CSV文件导入")
        print("5. 数据备份")
        print("6. 数据恢复")
        print("7. 返回主菜单")
        
        choice = input("请选择操作 (1-7): ").strip()
        
        if choice == '1':
            self.export_to_excel()
        elif choice == '2':
            self.import_from_excel()
        elif choice == '3':
            self.export_to_csv()
        elif choice == '4':
            self.import_from_csv()
        elif choice == '5':
            self.backup_data()
        elif choice == '6':
            self.restore_data()
        elif choice == '7':
            return
        else:
            print("无效选择！")
    
    def export_to_excel(self):
        """导出数据到Excel文件"""
        if not OPENPYXL_AVAILABLE or not PANDAS_AVAILABLE:
            print("\n=== 导出到Excel文件 ===")
            print("❌ Excel导出功能不可用！")
            print("请安装必要的库: pip install openpyxl pandas")
            return
        
        print("\n=== 导出到Excel文件 ===")
        if not self.students:
            print("暂无学生信息可导出！")
            return
        
        filename = input("请输入Excel文件名（不含扩展名）: ").strip()
        if not filename:
            filename = f"学生信息_{self.get_current_time().replace(':', '-').replace(' ', '_')}"
        
        filename += ".xlsx"
        
        try:
            # 创建DataFrame
            data = []
            for student in self.students:
                data.append({
                    '学号': student.student_id,
                    '姓名': student.name,
                    '年龄': student.age,
                    '专业': student.major,
                    '班级': student.class_name
                })
            
            df = pd.DataFrame(data)
            
            # 创建Excel文件
            with pd.ExcelWriter(filename, engine='openpyxl') as writer:
                df.to_excel(writer, sheet_name='学生信息', index=False)
                
                # 获取工作表
                worksheet = writer.sheets['学生信息']
                
                # 设置列宽
                column_widths = {'A': 12, 'B': 10, 'C': 8, 'D': 20, 'E': 15}
                for col, width in column_widths.items():
                    worksheet.column_dimensions[col].width = width
                
                # 设置标题行样式
                header_font = Font(bold=True, color="FFFFFF")
                header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
                header_alignment = Alignment(horizontal="center", vertical="center")
                
                for cell in worksheet[1]:
                    cell.font = header_font
                    cell.fill = header_fill
                    cell.alignment = header_alignment
                
                # 设置数据行样式
                data_alignment = Alignment(horizontal="center", vertical="center")
                for row in worksheet.iter_rows(min_row=2):
                    for cell in row:
                        cell.alignment = data_alignment
            
            print(f"数据已成功导出到: {filename}")
            print(f"共导出 {len(self.students)} 条学生记录")
            
        except Exception as e:
            print(f"导出Excel文件时出错: {e}")
    
    def import_from_excel(self):
        """从Excel文件导入数据"""
        if not OPENPYXL_AVAILABLE or not PANDAS_AVAILABLE:
            print("\n=== 从Excel文件导入 ===")
            print("❌ Excel导入功能不可用！")
            print("请安装必要的库: pip install openpyxl pandas")
            return
        
        print("\n=== 从Excel文件导入 ===")
        filename = input("请输入Excel文件路径: ").strip()
        
        if not filename:
            print("文件名不能为空！")
            return
        
        if not os.path.exists(filename):
            print(f"文件不存在: {filename}")
            return
        
        try:
            # 读取Excel文件
            df = pd.read_excel(filename, sheet_name=0)
            
            # 检查列名
            required_columns = ['学号', '姓名', '年龄', '专业', '班级']
            if not all(col in df.columns for col in required_columns):
                print(f"Excel文件格式错误！需要的列: {required_columns}")
                print(f"实际列: {list(df.columns)}")
                return
            
            # 导入数据
            imported_count = 0
            skipped_count = 0
            
            for index, row in df.iterrows():
                try:
                    student_id = str(row['学号']).strip()
                    name = str(row['姓名']).strip()
                    age = int(row['年龄'])
                    major = str(row['专业']).strip()
                    class_name = str(row['班级']).strip()
                    
                    # 验证数据
                    if not self.validate_student_id(student_id):
                        print(f"第{index+2}行: 学号格式错误 - {student_id}")
                        skipped_count += 1
                        continue
                    
                    if not self.validate_name(name):
                        print(f"第{index+2}行: 姓名格式错误 - {name}")
                        skipped_count += 1
                        continue
                    
                    if not self.validate_age(age):
                        print(f"第{index+2}行: 年龄范围错误 - {age}")
                        skipped_count += 1
                        continue
                    
                    # 检查学号是否已存在
                    if any(s.student_id == student_id for s in self.students):
                        print(f"第{index+2}行: 学号已存在 - {student_id}")
                        skipped_count += 1
                        continue
                    
                    # 创建学生对象
                    student = Student(student_id, name, age, major, class_name)
                    self.students.append(student)
                    imported_count += 1
                    
                except Exception as e:
                    print(f"第{index+2}行: 数据格式错误 - {e}")
                    skipped_count += 1
                    continue
            
            # 保存数据
            if imported_count > 0:
                self.save_data()
                print(f"导入完成！成功导入 {imported_count} 条记录，跳过 {skipped_count} 条记录")
            else:
                print("没有成功导入任何记录！")
                
        except Exception as e:
            print(f"导入Excel文件时出错: {e}")
    
    def export_to_csv(self):
        """导出数据到CSV文件"""
        if not PANDAS_AVAILABLE:
            print("\n=== 导出到CSV文件 ===")
            print("❌ CSV导出功能不可用！")
            print("请安装pandas库: pip install pandas")
            return
        
        print("\n=== 导出到CSV文件 ===")
        if not self.students:
            print("暂无学生信息可导出！")
            return
        
        filename = input("请输入CSV文件名（不含扩展名）: ").strip()
        if not filename:
            filename = f"学生信息_{self.get_current_time().replace(':', '-').replace(' ', '_')}"
        
        filename += ".csv"
        
        try:
            # 创建DataFrame
            data = []
            for student in self.students:
                data.append({
                    '学号': student.student_id,
                    '姓名': student.name,
                    '年龄': student.age,
                    '专业': student.major,
                    '班级': student.class_name
                })
            
            df = pd.DataFrame(data)
            df.to_csv(filename, index=False, encoding='utf-8-sig')
            
            print(f"数据已成功导出到: {filename}")
            print(f"共导出 {len(self.students)} 条学生记录")
            
        except Exception as e:
            print(f"导出CSV文件时出错: {e}")
    
    # 生成随机数
    def generate_random_number(self, min_value, max_value):
        """生成随机数"""
        return random.randint(min_value, max_value)
    
    def import_from_csv(self):
        """从CSV文件导入数据"""
        if not PANDAS_AVAILABLE:
            print("\n=== 从CSV文件导入 ===")
            print("❌ CSV导入功能不可用！")
            print("请安装pandas库: pip install pandas")
            return
        
        print("\n=== 从CSV文件导入 ===")
        filename = input("请输入CSV文件路径: ").strip()
        
        if not filename:
            print("文件名不能为空！")
            return
        
        if not os.path.exists(filename):
            print(f"文件不存在: {filename}")
            return
        
        try:
            # 读取CSV文件
            df = pd.read_csv(filename, encoding='utf-8-sig')
            
            # 检查列名
            required_columns = ['学号', '姓名', '年龄', '专业', '班级']
            if not all(col in df.columns for col in required_columns):
                print(f"CSV文件格式错误！需要的列: {required_columns}")
                print(f"实际列: {list(df.columns)}")
                return
            
            # 导入数据
            imported_count = 0
            skipped_count = 0
            
            for index, row in df.iterrows():
                try:
                    student_id = str(row['学号']).strip()
                    name = str(row['姓名']).strip()
                    age = int(row['年龄'])
                    major = str(row['专业']).strip()
                    class_name = str(row['班级']).strip()
                    
                    # 验证数据
                    if not self.validate_student_id(student_id):
                        print(f"第{index+2}行: 学号格式错误 - {student_id}")
                        skipped_count += 1
                        continue
                    
                    if not self.validate_name(name):
                        print(f"第{index+2}行: 姓名格式错误 - {name}")
                        skipped_count += 1
                        continue
                    
                    if not self.validate_age(age):
                        print(f"第{index+2}行: 年龄范围错误 - {age}")
                        skipped_count += 1
                        continue
                    
                    # 检查学号是否已存在
                    if any(s.student_id == student_id for s in self.students):
                        print(f"第{index+2}行: 学号已存在 - {student_id}")
                        skipped_count += 1
                        continue
                    
                    # 创建学生对象
                    student = Student(student_id, name, age, major, class_name)
                    self.students.append(student)
                    imported_count += 1
                    
                except Exception as e:
                    print(f"第{index+2}行: 数据格式错误 - {e}")
                    skipped_count += 1
                    continue
            
            # 保存数据
            if imported_count > 0:
                self.save_data()
                print(f"导入完成！成功导入 {imported_count} 条记录，跳过 {skipped_count} 条记录")
            else:
                print("没有成功导入任何记录！")
                
        except Exception as e:
            print(f"导入CSV文件时出错: {e}")
    
    def backup_data(self):
        """数据备份"""
        print("\n=== 数据备份 ===")
        if not self.students:
            print("暂无数据可备份！")
            return
        
        backup_filename = f"学生信息备份_{self.get_current_time().replace(':', '-').replace(' ', '_')}.txt"
        
        try:
            with open(backup_filename, 'w', encoding='utf-8') as f:
                for student in self.students:
                    f.write(student.to_string() + '\n')
            
            print(f"数据备份成功！备份文件: {backup_filename}")
            print(f"共备份 {len(self.students)} 条学生记录")
            
        except Exception as e:
            print(f"数据备份时出错: {e}")
    
    def restore_data(self):
        """数据恢复"""
        print("\n=== 数据恢复 ===")
        backup_filename = input("请输入备份文件名: ").strip()
        
        if not backup_filename:
            print("文件名不能为空！")
            return
        
        if not os.path.exists(backup_filename):
            print(f"备份文件不存在: {backup_filename}")
            return
        
        try:
            # 备份当前数据
            current_backup = f"当前数据备份_{self.get_current_time().replace(':', '-').replace(' ', '_')}.txt"
            with open(current_backup, 'w', encoding='utf-8') as f:
                for student in self.students:
                    f.write(student.to_string() + '\n')
            
            # 清空当前数据
            self.students.clear()
            
            # 从备份文件恢复
            with open(backup_filename, 'r', encoding='utf-8') as f:
                for line in f:
                    if line.strip():
                        try:
                            student = Student.from_string(line)
                            self.students.append(student)
                        except ValueError as e:
                            print(f"恢复数据时出错: {e}")
                            continue
            
            # 保存恢复的数据
            self.save_data()
            
            print(f"数据恢复成功！从 {backup_filename} 恢复了 {len(self.students)} 条记录")
            print(f"当前数据已备份到: {current_backup}")
            
        except Exception as e:
            print(f"数据恢复时出错: {e}")
    
    def batch_operations_menu(self):
        """批量操作菜单"""
        print("\n=== 批量操作 ===")
        print("1. 批量添加学生")
        print("2. 批量删除学生")
        print("3. 批量修改学生信息")
        print("4. 批量导入学生数据")
        print("5. 返回主菜单")
        
        choice = input("请选择操作 (1-5): ").strip()
        
        if choice == '1':
            self.batch_add_students()
        elif choice == '2':
            self.batch_delete_students()
        elif choice == '3':
            self.batch_update_students()
        elif choice == '4':
            self.batch_import_students()
        elif choice == '5':
            return
        else:
            print("无效选择！")
    
    def batch_add_students(self):
        """批量添加学生"""
        print("\n=== 批量添加学生 ===")
        print("请输入学生信息，每行一个学生，格式：学号,姓名,年龄,专业,班级")
        print("输入 'done' 结束输入")
        
        students_to_add = []
        line_count = 0
        
        while True:
            line_count += 1
            line = input(f"第{line_count}行: ").strip()
            
            if line.lower() == 'done':
                break
            
            if not line:
                continue
            
            try:
                parts = line.split(',')
                if len(parts) != 5:
                    print(f"第{line_count}行: 格式错误，需要5个字段")
                    continue
                
                student_id, name, age_str, major, class_name = [part.strip() for part in parts]
                age = int(age_str)
                
                # 验证数据
                if not self.validate_student_id(student_id):
                    print(f"第{line_count}行: 学号格式错误 - {student_id}")
                    continue
                
                if not self.validate_name(name):
                    print(f"第{line_count}行: 姓名格式错误 - {name}")
                    continue
                
                if not self.validate_age(age):
                    print(f"第{line_count}行: 年龄范围错误 - {age}")
                    continue
                
                # 检查学号是否已存在
                if any(s.student_id == student_id for s in self.students):
                    print(f"第{line_count}行: 学号已存在 - {student_id}")
                    continue
                
                student = Student(student_id, name, age, major, class_name)
                students_to_add.append(student)
                
            except ValueError:
                print(f"第{line_count}行: 数据格式错误")
                continue
        
        if students_to_add:
            self.students.extend(students_to_add)
            self.save_data()
            print(f"批量添加完成！成功添加 {len(students_to_add)} 名学生")
        else:
            print("没有添加任何学生！")
    
    def batch_delete_students(self):
        """批量删除学生"""
        print("\n=== 批量删除学生 ===")
        if not self.students:
            print("暂无学生信息！")
            return
        
        print("请输入要删除的学生学号，每行一个，输入 'done' 结束")
        
        student_ids_to_delete = []
        while True:
            student_id = input("学号: ").strip()
            if student_id.lower() == 'done':
                break
            if student_id:
                student_ids_to_delete.append(student_id)
        
        if not student_ids_to_delete:
            print("没有输入任何学号！")
            return
        
        deleted_count = 0
        for student_id in student_ids_to_delete:
            for i, student in enumerate(self.students):
                if student.student_id == student_id:
                    del self.students[i]
                    deleted_count += 1
                    break
        
        if deleted_count > 0:
            self.save_data()
            print(f"批量删除完成！成功删除 {deleted_count} 名学生")
        else:
            print("没有找到要删除的学生！")
    
    def batch_update_students(self):
        """批量修改学生信息"""
        print("\n=== 批量修改学生信息 ===")
        print("此功能需要指定修改的字段和条件")
        print("1. 按专业修改")
        print("2. 按班级修改")
        print("3. 按年龄范围修改")
        
        choice = input("请选择修改方式 (1-3): ").strip()
        
        if choice == '1':
            self.batch_update_by_major()
        elif choice == '2':
            self.batch_update_by_class()
        elif choice == '3':
            self.batch_update_by_age_range()
        else:
            print("无效选择！")
    
    def batch_update_by_major(self):
        """按专业批量修改"""
        major = input("请输入要修改的专业: ").strip()
        if not major:
            print("专业不能为空！")
            return
        
        # 查找匹配的学生
        matching_students = [s for s in self.students if major in s.major]
        if not matching_students:
            print(f"没有找到专业包含 '{major}' 的学生！")
            return
        
        print(f"找到 {len(matching_students)} 名匹配的学生")
        self.display_students_table(matching_students)
        
        new_major = input("请输入新的专业: ").strip()
        if not new_major:
            print("新专业不能为空！")
            return
        
        confirm = input(f"确认将 {len(matching_students)} 名学生的专业从 '{major}' 修改为 '{new_major}'？(y/n): ").strip().lower()
        if confirm == 'y':
            for student in matching_students:
                student.major = new_major
            self.save_data()
            print("批量修改完成！")
        else:
            print("取消修改操作")
    
    def batch_update_by_class(self):
        """按班级批量修改"""
        class_name = input("请输入要修改的班级: ").strip()
        if not class_name:
            print("班级不能为空！")
            return
        
        # 查找匹配的学生
        matching_students = [s for s in self.students if class_name in s.class_name]
        if not matching_students:
            print(f"没有找到班级包含 '{class_name}' 的学生！")
            return
        
        print(f"找到 {len(matching_students)} 名匹配的学生")
        self.display_students_table(matching_students)
        
        new_class = input("请输入新的班级: ").strip()
        if not new_class:
            print("新班级不能为空！")
            return
        
        confirm = input(f"确认将 {len(matching_students)} 名学生的班级从 '{class_name}' 修改为 '{new_class}'？(y/n): ").strip().lower()
        if confirm == 'y':
            for student in matching_students:
                student.class_name = new_class
            self.save_data()
            print("批量修改完成！")
        else:
            print("取消修改操作")
    
    def batch_update_by_age_range(self):
        """按年龄范围批量修改"""
        try:
            min_age = int(input("请输入最小年龄: ").strip())
            max_age = int(input("请输入最大年龄: ").strip())
            
            if min_age > max_age:
                print("最小年龄不能大于最大年龄！")
                return
            
            # 查找匹配的学生
            matching_students = [s for s in self.students if min_age <= s.age <= max_age]
            if not matching_students:
                print(f"没有找到年龄在 {min_age}-{max_age} 岁之间的学生！")
                return
            
            print(f"找到 {len(matching_students)} 名匹配的学生")
            self.display_students_table(matching_students)
            
            print("请选择要修改的字段:")
            print("1. 专业")
            print("2. 班级")
            field_choice = input("请选择 (1-2): ").strip()
            
            if field_choice == '1':
                new_value = input("请输入新的专业: ").strip()
                if not new_value:
                    print("新专业不能为空！")
                    return
                confirm = input(f"确认将 {len(matching_students)} 名学生的专业修改为 '{new_value}'？(y/n): ").strip().lower()
                if confirm == 'y':
                    for student in matching_students:
                        student.major = new_value
                    self.save_data()
                    print("批量修改完成！")
                else:
                    print("取消修改操作")
            elif field_choice == '2':
                new_value = input("请输入新的班级: ").strip()
                if not new_value:
                    print("新班级不能为空！")
                    return
                confirm = input(f"确认将 {len(matching_students)} 名学生的班级修改为 '{new_value}'？(y/n): ").strip().lower()
                if confirm == 'y':
                    for student in matching_students:
                        student.class_name = new_value
                    self.save_data()
                    print("批量修改完成！")
                else:
                    print("取消修改操作")
            else:
                print("无效选择！")
                
        except ValueError:
            print("年龄格式错误，请输入数字！")
    
    def batch_import_students(self):
        """批量导入学生数据"""
        print("\n=== 批量导入学生数据 ===")
        print("1. 从Excel文件导入")
        print("2. 从CSV文件导入")
        print("3. 从文本文件导入")
        
        choice = input("请选择导入方式 (1-3): ").strip()
        
        if choice == '1':
            self.import_from_excel()
        elif choice == '2':
            self.import_from_csv()
        elif choice == '3':
            self.import_from_text_file()
        else:
            print("无效选择！")
    
    def import_from_text_file(self):
        """从文本文件导入数据"""
        print("\n=== 从文本文件导入 ===")
        filename = input("请输入文本文件路径: ").strip()
        
        if not filename:
            print("文件名不能为空！")
            return
        
        if not os.path.exists(filename):
            print(f"文件不存在: {filename}")
            return
        
        try:
            imported_count = 0
            skipped_count = 0
            
            with open(filename, 'r', encoding='utf-8') as f:
                for line_num, line in enumerate(f, 1):
                    line = line.strip()
                    if not line:
                        continue
                    
                    try:
                        student = Student.from_string(line)
                        
                        # 验证数据
                        if not self.validate_student_id(student.student_id):
                            print(f"第{line_num}行: 学号格式错误 - {student.student_id}")
                            skipped_count += 1
                            continue
                        
                        if not self.validate_name(student.name):
                            print(f"第{line_num}行: 姓名格式错误 - {student.name}")
                            skipped_count += 1
                            continue
                        
                        if not self.validate_age(student.age):
                            print(f"第{line_num}行: 年龄范围错误 - {student.age}")
                            skipped_count += 1
                            continue
                        
                        # 检查学号是否已存在
                        if any(s.student_id == student.student_id for s in self.students):
                            print(f"第{line_num}行: 学号已存在 - {student.student_id}")
                            skipped_count += 1
                            continue
                        
                        self.students.append(student)
                        imported_count += 1
                        
                    except ValueError as e:
                        print(f"第{line_num}行: 数据格式错误 - {e}")
                        skipped_count += 1
                        continue
            
            # 保存数据
            if imported_count > 0:
                self.save_data()
                print(f"导入完成！成功导入 {imported_count} 条记录，跳过 {skipped_count} 条记录")
            else:
                print("没有成功导入任何记录！")
                
        except Exception as e:
            print(f"导入文本文件时出错: {e}")
    
    # ==================== 课程管理功能 ====================
    
    def course_management_menu(self):
        """课程管理菜单"""
        print("\n=== 课程管理 ===")
        print("1. 添加课程")
        print("2. 删除课程")
        print("3. 修改课程信息")
        print("4. 查询课程")
        print("5. 显示所有课程")
        print("6. 返回主菜单")
        
        choice = input("请选择操作 (1-6): ").strip()
        
        if choice == '1':
            self.add_course()
        elif choice == '2':
            self.delete_course()
        elif choice == '3':
            self.update_course()
        elif choice == '4':
            self.query_course()
        elif choice == '5':
            self.display_all_courses()
        elif choice == '6':
            return
        else:
            print("无效选择！")
    
    def add_course(self):
        """添加课程"""
        print("\n=== 添加课程 ===")
        try:
            course_id = input("请输入课程代码: ").strip()
            if not course_id:
                print("课程代码不能为空！")
                return
            
            # 检查课程代码是否已存在
            if any(c.course_id == course_id for c in self.courses):
                print("该课程代码已存在！")
                return
            
            course_name = input("请输入课程名称: ").strip()
            if not course_name:
                print("课程名称不能为空！")
                return
            
            credits = float(input("请输入学分: "))
            if credits <= 0:
                print("学分必须大于0！")
                return
            
            teacher = input("请输入授课教师（可选）: ").strip()
            
            course = Course(course_id, course_name, credits, teacher)
            self.courses.append(course)
            self.save_courses()
            print("课程添加成功！")
            
        except ValueError:
            print("输入格式错误，请重新输入！")
        except Exception as e:
            print(f"添加课程时出错: {e}")
    
    def delete_course(self):
        """删除课程"""
        print("\n=== 删除课程 ===")
        course_id = input("请输入要删除的课程代码: ").strip()
        
        if not course_id:
            print("课程代码不能为空！")
            return
        
        # 查找课程
        for i, course in enumerate(self.courses):
            if course.course_id == course_id:
                print(f"找到课程: {course}")
                
                # 检查是否有相关成绩记录
                related_grades = [g for g in self.grades if g.course_id == course_id]
                if related_grades:
                    print(f"警告：该课程有 {len(related_grades)} 条成绩记录！")
                    confirm = input("确认删除课程及其所有成绩记录？(y/n): ").strip().lower()
                    if confirm == 'y':
                        # 删除相关成绩记录
                        self.grades = [g for g in self.grades if g.course_id != course_id]
                        del self.courses[i]
                        self.save_courses()
                        self.save_grades()
                        print("课程及相关成绩记录删除成功！")
                    else:
                        print("取消删除操作")
                else:
                    confirm = input("确认删除？(y/n): ").strip().lower()
                    if confirm == 'y':
                        del self.courses[i]
                        self.save_courses()
                        print("课程删除成功！")
                    else:
                        print("取消删除操作")
                return
        
        print("未找到该课程代码！")
    
    def update_course(self):
        """修改课程信息"""
        print("\n=== 修改课程信息 ===")
        course_id = input("请输入要修改的课程代码: ").strip()
        
        if not course_id:
            print("课程代码不能为空！")
            return
        
        # 查找课程
        for course in self.courses:
            if course.course_id == course_id:
                print(f"当前课程信息: {course}")
                print("请输入新的信息（直接回车保持原值）:")
                
                try:
                    new_name = input(f"课程名称 [{course.course_name}]: ").strip()
                    if new_name:
                        course.course_name = new_name
                    
                    new_credits = input(f"学分 [{course.credits}]: ").strip()
                    if new_credits:
                        credits = float(new_credits)
                        if credits > 0:
                            course.credits = credits
                        else:
                            print("学分必须大于0，保持原值")
                    
                    new_teacher = input(f"授课教师 [{course.teacher}]: ").strip()
                    if new_teacher:
                        course.teacher = new_teacher
                    
                    self.save_courses()
                    print("课程信息修改成功！")
                    print(f"修改后信息: {course}")
                except ValueError:
                    print("输入格式错误，修改失败！")
                return
        
        print("未找到该课程代码！")
    
    def query_course(self):
        """查询课程"""
        print("\n=== 查询课程 ===")
        course_id = input("请输入课程代码: ").strip()
        
        if not course_id:
            print("课程代码不能为空！")
            return
        
        for course in self.courses:
            if course.course_id == course_id:
                print("查询结果:")
                self.display_courses_table([course])
                return
        
        print("未找到该课程代码！")
    
    def display_all_courses(self):
        """显示所有课程"""
        print("\n=== 所有课程信息 ===")
        if not self.courses:
            print("暂无课程信息！")
            return
        
        print(f"共有 {len(self.courses)} 门课程：")
        self.display_courses_table(self.courses)
    
    def display_courses_table(self, courses: List[Course]):
        """以表格形式显示课程信息"""
        if not courses:
            print("暂无课程信息！")
            return
        
        # 计算各列的最大宽度
        max_id_len = max(len("课程代码"), max(len(c.course_id) for c in courses))
        max_name_len = max(len("课程名称"), max(len(c.course_name) for c in courses))
        max_credits_len = max(len("学分"), max(len(str(c.credits)) for c in courses))
        max_teacher_len = max(len("授课教师"), max(len(c.teacher) for c in courses))
        
        # 设置最小宽度
        max_id_len = max(max_id_len, 8)
        max_name_len = max(max_name_len, 12)
        max_credits_len = max(max_credits_len, 6)
        max_teacher_len = max(max_teacher_len, 10)
        
        # 创建表格边框
        def create_line():
            return "+" + "-" * (max_id_len + 2) + "+" + "-" * (max_name_len + 2) + "+" + "-" * (max_credits_len + 2) + "+" + "-" * (max_teacher_len + 2) + "+"
        
        def create_row(items):
            return "| " + f"{items[0]:<{max_id_len}} | {items[1]:<{max_name_len}} | {items[2]:<{max_credits_len}} | {items[3]:<{max_teacher_len}} |"
        
        # 打印表头
        print(create_line())
        print(create_row(["课程代码", "课程名称", "学分", "授课教师"]))
        print(create_line())
        
        # 打印数据行
        for course in courses:
            print(create_row([course.course_id, course.course_name, str(course.credits), course.teacher]))
        
        print(create_line())
        print(f"共 {len(courses)} 条记录")
    
    # ==================== 成绩管理功能 ====================
    
    def grade_management_menu(self):
        """成绩管理菜单"""
        print("\n=== 成绩管理 ===")
        print("1. 录入成绩")
        print("2. 查询成绩")
        print("3. 修改成绩")
        print("4. 删除成绩")
        print("5. 成绩统计分析")
        print("6. 计算GPA")
        print("7. 成绩排名")
        print("8. 生成成绩报告")
        print("9. 返回主菜单")
        
        choice = input("请选择操作 (1-9): ").strip()
        
        if choice == '1':
            self.add_grade()
        elif choice == '2':
            self.query_grades()
        elif choice == '3':
            self.update_grade()
        elif choice == '4':
            self.delete_grade()
        elif choice == '5':
            self.grade_statistics()
        elif choice == '6':
            self.calculate_gpa()
        elif choice == '7':
            self.grade_ranking()
        elif choice == '8':
            self.generate_grade_report()
        elif choice == '9':
            return
        else:
            print("无效选择！")
    
    def add_grade(self):
        """录入成绩"""
        print("\n=== 录入成绩 ===")
        try:
            student_id = input("请输入学号: ").strip()
            if not student_id:
                print("学号不能为空！")
                return
            
            # 验证学生是否存在
            student = None
            for s in self.students:
                if s.student_id == student_id:
                    student = s
                    break
            
            if not student:
                print("该学号不存在！")
                return
            
            print(f"学生信息: {student.name} ({student.student_id})")
            
            course_id = input("请输入课程代码: ").strip()
            if not course_id:
                print("课程代码不能为空！")
                return
            
            # 验证课程是否存在
            course = None
            for c in self.courses:
                if c.course_id == course_id:
                    course = c
                    break
            
            if not course:
                print("该课程代码不存在！请先添加课程信息。")
                return
            
            print(f"课程信息: {course.course_name} ({course.course_id})")
            
            score = float(input("请输入成绩 (0-100): "))
            if not (0 <= score <= 100):
                print("成绩必须在0-100之间！")
                return
            
            semester = input("请输入学期 (如: 2024-1): ").strip()
            if not semester:
                print("学期不能为空！")
                return
            
            exam_type = input("请输入考试类型 (期末考试/期中考试/平时成绩) [期末考试]: ").strip()
            if not exam_type:
                exam_type = "期末考试"
            
            # 检查是否已有相同记录
            existing_grade = None
            for g in self.grades:
                if (g.student_id == student_id and g.course_id == course_id and 
                    g.semester == semester and g.exam_type == exam_type):
                    existing_grade = g
                    break
            
            if existing_grade:
                print(f"该学生在 {semester} 学期的 {course.course_name} {exam_type} 成绩已存在: {existing_grade.score}")
                confirm = input("是否覆盖原成绩？(y/n): ").strip().lower()
                if confirm == 'y':
                    existing_grade.score = score
                    self.save_grades()
                    print("成绩更新成功！")
                else:
                    print("取消录入操作")
            else:
                grade = Grade(student_id, course_id, score, semester, exam_type)
                self.grades.append(grade)
                self.save_grades()
                print("成绩录入成功！")
                print(f"成绩信息: {student.name} - {course.course_name} - {score}分 - 绩点: {grade.get_grade_point()}")
            
        except ValueError:
            print("输入格式错误，请重新输入！")
        except Exception as e:
            print(f"录入成绩时出错: {e}")
    
    def query_grades(self):
        """查询成绩"""
        print("\n=== 查询成绩 ===")
        print("1. 按学号查询")
        print("2. 按课程查询")
        print("3. 按学期查询")
        print("4. 查询所有成绩")
        
        choice = input("请选择查询方式 (1-4): ").strip()
        
        if choice == '1':
            self.query_grades_by_student()
        elif choice == '2':
            self.query_grades_by_course()
        elif choice == '3':
            self.query_grades_by_semester()
        elif choice == '4':
            self.query_all_grades()
        else:
            print("无效选择！")
    
    def query_grades_by_student(self):
        """按学号查询成绩"""
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        # 验证学生是否存在
        student = None
        for s in self.students:
            if s.student_id == student_id:
                student = s
                break
        
        if not student:
            print("该学号不存在！")
            return
        
        student_grades = [g for g in self.grades if g.student_id == student_id]
        if student_grades:
            print(f"\n{student.name} ({student_id}) 的成绩记录：")
            self.display_grades_table(student_grades)
        else:
            print("该学生暂无成绩记录！")
    
    def query_grades_by_course(self):
        """按课程查询成绩"""
        course_id = input("请输入课程代码: ").strip()
        if not course_id:
            print("课程代码不能为空！")
            return
        
        # 验证课程是否存在
        course = None
        for c in self.courses:
            if c.course_id == course_id:
                course = c
                break
        
        if not course:
            print("该课程代码不存在！")
            return
        
        course_grades = [g for g in self.grades if g.course_id == course_id]
        if course_grades:
            print(f"\n{course.course_name} ({course_id}) 的成绩记录：")
            self.display_grades_table(course_grades)
        else:
            print("该课程暂无成绩记录！")
    
    def query_grades_by_semester(self):
        """按学期查询成绩"""
        semester = input("请输入学期 (如: 2024-1): ").strip()
        if not semester:
            print("学期不能为空！")
            return
        
        semester_grades = [g for g in self.grades if g.semester == semester]
        if semester_grades:
            print(f"\n{semester} 学期的成绩记录：")
            self.display_grades_table(semester_grades)
        else:
            print("该学期暂无成绩记录！")
    
    def query_all_grades(self):
        """查询所有成绩"""
        if not self.grades:
            print("暂无成绩记录！")
            return
        
        print(f"\n所有成绩记录（共 {len(self.grades)} 条）：")
        self.display_grades_table(self.grades)
    
    def display_grades_table(self, grades: List[Grade]):
        """以表格形式显示成绩信息"""
        if not grades:
            print("暂无成绩记录！")
            return
        
        # 获取学生和课程信息用于显示
        student_dict = {s.student_id: s.name for s in self.students}
        course_dict = {c.course_id: c.course_name for c in self.courses}
        
        print("-" * 100)
        print(f"{'学号':<10} {'姓名':<8} {'课程代码':<10} {'课程名称':<15} {'成绩':<6} {'绩点':<6} {'等级':<4} {'学期':<10} {'类型':<10}")
        print("-" * 100)
        
        for grade in grades:
            student_name = student_dict.get(grade.student_id, "未知")
            course_name = course_dict.get(grade.course_id, "未知")
            
            print(f"{grade.student_id:<10} {student_name:<8} {grade.course_id:<10} {course_name:<15} "
                  f"{grade.score:<6.1f} {grade.get_grade_point():<6.1f} {grade.get_letter_grade():<4} "
                  f"{grade.semester:<10} {grade.exam_type:<10}")
        
        print("-" * 100)
        print(f"共 {len(grades)} 条记录")
    
    def update_grade(self):
        """修改成绩"""
        print("\n=== 修改成绩 ===")
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        course_id = input("请输入课程代码: ").strip()
        if not course_id:
            print("课程代码不能为空！")
            return
        
        semester = input("请输入学期: ").strip()
        if not semester:
            print("学期不能为空！")
            return
        
        exam_type = input("请输入考试类型 [期末考试]: ").strip()
        if not exam_type:
            exam_type = "期末考试"
        
        # 查找成绩记录
        for grade in self.grades:
            if (grade.student_id == student_id and grade.course_id == course_id and 
                grade.semester == semester and grade.exam_type == exam_type):
                print(f"找到成绩记录: {grade}")
                try:
                    new_score = float(input("请输入新成绩 (0-100): "))
                    if not (0 <= new_score <= 100):
                        print("成绩必须在0-100之间！")
                        return
                    
                    old_score = grade.score
                    grade.score = new_score
                    self.save_grades()
                    print(f"成绩修改成功！{old_score} -> {new_score}")
                    print(f"新绩点: {grade.get_grade_point()}")
                except ValueError:
                    print("输入格式错误！")
                return
        
        print("未找到匹配的成绩记录！")
    
    def delete_grade(self):
        """删除成绩"""
        print("\n=== 删除成绩 ===")
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        course_id = input("请输入课程代码: ").strip()
        if not course_id:
            print("课程代码不能为空！")
            return
        
        semester = input("请输入学期: ").strip()
        if not semester:
            print("学期不能为空！")
            return
        
        exam_type = input("请输入考试类型 [期末考试]: ").strip()
        if not exam_type:
            exam_type = "期末考试"
        
        # 查找并删除成绩记录
        for i, grade in enumerate(self.grades):
            if (grade.student_id == student_id and grade.course_id == course_id and 
                grade.semester == semester and grade.exam_type == exam_type):
                print(f"找到成绩记录: {grade}")
                confirm = input("确认删除？(y/n): ").strip().lower()
                if confirm == 'y':
                    del self.grades[i]
                    self.save_grades()
                    print("成绩删除成功！")
                else:
                    print("取消删除操作")
                return
        
        print("未找到匹配的成绩记录！")
    
    def calculate_gpa(self):
        """计算GPA"""
        print("\n=== 计算GPA ===")
        print("1. 计算单个学生GPA")
        print("2. 计算所有学生GPA")
        
        choice = input("请选择 (1-2): ").strip()
        
        if choice == '1':
            self.calculate_student_gpa()
        elif choice == '2':
            self.calculate_all_students_gpa()
        else:
            print("无效选择！")
    
    def calculate_student_gpa(self):
        """计算单个学生的GPA"""
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        # 验证学生是否存在
        student = None
        for s in self.students:
            if s.student_id == student_id:
                student = s
                break
        
        if not student:
            print("该学号不存在！")
            return
        
        # 获取学生的所有期末考试成绩
        student_grades = [g for g in self.grades if g.student_id == student_id and g.exam_type == "期末考试"]
        
        if not student_grades:
            print("该学生暂无期末考试成绩记录！")
            return
        
        # 计算GPA
        total_grade_points = 0
        total_credits = 0
        
        print(f"\n{student.name} ({student_id}) 的GPA计算：")
        print("-" * 80)
        print(f"{'课程代码':<10} {'课程名称':<15} {'成绩':<6} {'绩点':<6} {'学分':<6} {'加权绩点':<8}")
        print("-" * 80)
        
        for grade in student_grades:
            # 查找对应课程的学分
            course = None
            for c in self.courses:
                if c.course_id == grade.course_id:
                    course = c
                    break
            
            if course:
                grade_point = grade.get_grade_point()
                weighted_gp = grade_point * course.credits
                total_grade_points += weighted_gp
                total_credits += course.credits
                
                print(f"{course.course_id:<10} {course.course_name:<15} {grade.score:<6.1f} "
                      f"{grade_point:<6.1f} {course.credits:<6.1f} {weighted_gp:<8.2f}")
        
        print("-" * 80)
        
        if total_credits > 0:
            gpa = total_grade_points / total_credits
            print(f"总学分: {total_credits:.1f}")
            print(f"总加权绩点: {total_grade_points:.2f}")
            print(f"GPA: {gpa:.3f}")
        else:
            print("无法计算GPA：没有有效的课程学分信息")
    
    def calculate_all_students_gpa(self):
        """计算所有学生的GPA"""
        print("\n=== 所有学生GPA ===")
        
        if not self.students:
            print("暂无学生信息！")
            return
        
        gpa_list = []
        
        for student in self.students:
            # 获取学生的所有期末考试成绩
            student_grades = [g for g in self.grades if g.student_id == student.student_id and g.exam_type == "期末考试"]
            
            if not student_grades:
                continue
            
            # 计算GPA
            total_grade_points = 0
            total_credits = 0
            
            for grade in student_grades:
                # 查找对应课程的学分
                course = None
                for c in self.courses:
                    if c.course_id == grade.course_id:
                        course = c
                        break
                
                if course:
                    grade_point = grade.get_grade_point()
                    weighted_gp = grade_point * course.credits
                    total_grade_points += weighted_gp
                    total_credits += course.credits
            
            if total_credits > 0:
                gpa = total_grade_points / total_credits
                gpa_list.append((student, gpa, total_credits))
        
        if not gpa_list:
            print("暂无可计算GPA的学生！")
            return
        
        # 按GPA降序排序
        gpa_list.sort(key=lambda x: x[1], reverse=True)
        
        print("-" * 70)
        print(f"{'排名':<4} {'学号':<10} {'姓名':<8} {'专业':<15} {'GPA':<8} {'总学分':<8}")
        print("-" * 70)
        
        for i, (student, gpa, credits) in enumerate(gpa_list, 1):
            print(f"{i:<4} {student.student_id:<10} {student.name:<8} {student.major:<15} "
                  f"{gpa:<8.3f} {credits:<8.1f}")
        
        print("-" * 70)
        print(f"共 {len(gpa_list)} 名学生")
    
    def grade_statistics(self):
        """成绩统计分析"""
        print("\n=== 成绩统计分析 ===")
        print("1. 按课程统计成绩")
        print("2. 按学期统计成绩")
        print("3. 成绩分布统计")
        print("4. 不及格统计")
        
        choice = input("请选择统计方式 (1-4): ").strip()
        
        if choice == '1':
            self.statistics_by_course_grade()
        elif choice == '2':
            self.statistics_by_semester_grade()
        elif choice == '3':
            self.grade_distribution_statistics()
        elif choice == '4':
            self.failing_grade_statistics()
        else:
            print("无效选择！")
    
    def statistics_by_course_grade(self):
        """按课程统计成绩"""
        course_id = input("请输入课程代码: ").strip()
        if not course_id:
            print("课程代码不能为空！")
            return
        
        # 验证课程是否存在
        course = None
        for c in self.courses:
            if c.course_id == course_id:
                course = c
                break
        
        if not course:
            print("该课程代码不存在！")
            return
        
        course_grades = [g for g in self.grades if g.course_id == course_id]
        
        if not course_grades:
            print("该课程暂无成绩记录！")
            return
        
        scores = [g.score for g in course_grades]
        
        print(f"\n{course.course_name} ({course_id}) 成绩统计：")
        print("-" * 50)
        print(f"总人数: {len(scores)}")
        print(f"最高分: {max(scores):.1f}")
        print(f"最低分: {min(scores):.1f}")
        print(f"平均分: {sum(scores)/len(scores):.2f}")
        
        # 及格率统计
        pass_count = len([s for s in scores if s >= 60])
        pass_rate = (pass_count / len(scores)) * 100
        print(f"及格人数: {pass_count}")
        print(f"及格率: {pass_rate:.1f}%")
        
        # 等级分布
        grade_counts = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'F': 0}
        for grade in course_grades:
            letter_grade = grade.get_letter_grade()
            grade_counts[letter_grade] += 1
        
        print("\n等级分布:")
        for letter, count in grade_counts.items():
            percentage = (count / len(course_grades)) * 100
            print(f"  {letter}: {count} 人 ({percentage:.1f}%)")
    
    def grade_ranking(self):
        """成绩排名"""
        print("\n=== 成绩排名 ===")
        print("1. 按课程排名")
        print("2. 按GPA排名")
        
        choice = input("请选择排名方式 (1-2): ").strip()
        
        if choice == '1':
            self.course_grade_ranking()
        elif choice == '2':
            self.gpa_ranking()
        else:
            print("无效选择！")
    
    def course_grade_ranking(self):
        """按课程成绩排名"""
        course_id = input("请输入课程代码: ").strip()
        if not course_id:
            print("课程代码不能为空！")
            return
        
        # 验证课程是否存在
        course = None
        for c in self.courses:
            if c.course_id == course_id:
                course = c
                break
        
        if not course:
            print("该课程代码不存在！")
            return
        
        course_grades = [g for g in self.grades if g.course_id == course_id and g.exam_type == "期末考试"]
        
        if not course_grades:
            print("该课程暂无期末考试成绩记录！")
            return
        
        # 按成绩降序排序
        course_grades.sort(key=lambda x: x.score, reverse=True)
        
        print(f"\n{course.course_name} ({course_id}) 成绩排名：")
        print("-" * 60)
        print(f"{'排名':<4} {'学号':<10} {'姓名':<8} {'成绩':<6} {'等级':<4} {'绩点':<6}")
        print("-" * 60)
        
        student_dict = {s.student_id: s.name for s in self.students}
        
        for i, grade in enumerate(course_grades, 1):
            student_name = student_dict.get(grade.student_id, "未知")
            print(f"{i:<4} {grade.student_id:<10} {student_name:<8} {grade.score:<6.1f} "
                  f"{grade.get_letter_grade():<4} {grade.get_grade_point():<6.1f}")
        
        print("-" * 60)
    
    def gpa_ranking(self):
        """GPA排名"""
        self.calculate_all_students_gpa()
    
    def generate_grade_report(self):
        """生成成绩报告"""
        print("\n=== 生成成绩报告 ===")
        print("1. 学生个人成绩报告")
        print("2. 课程成绩报告")
        print("3. 班级成绩报告")
        
        choice = input("请选择报告类型 (1-3): ").strip()
        
        if choice == '1':
            self.generate_student_report()
        elif choice == '2':
            self.generate_course_report()
        elif choice == '3':
            self.generate_class_report()
        else:
            print("无效选择！")
    
    def generate_student_report(self):
        """生成学生个人成绩报告"""
        student_id = input("请输入学号: ").strip()
        if not student_id:
            print("学号不能为空！")
            return
        
        # 验证学生是否存在
        student = None
        for s in self.students:
            if s.student_id == student_id:
                student = s
                break
        
        if not student:
            print("该学号不存在！")
            return
        
        student_grades = [g for g in self.grades if g.student_id == student_id]
        
        if not student_grades:
            print("该学生暂无成绩记录！")
            return
        
        # 生成报告
        report_filename = f"{student.name}_{student_id}_成绩报告.txt"
        
        try:
            with open(report_filename, 'w', encoding='utf-8') as f:
                f.write("=" * 60 + "\n")
                f.write(f"学生成绩报告\n")
                f.write("=" * 60 + "\n")
                f.write(f"学号: {student.student_id}\n")
                f.write(f"姓名: {student.name}\n")
                f.write(f"专业: {student.major}\n")
                f.write(f"班级: {student.class_name}\n")
                f.write(f"报告生成时间: {self.get_current_time()}\n")
                f.write("=" * 60 + "\n\n")
                
                # 按学期分组显示成绩
                semester_grades = {}
                for grade in student_grades:
                    if grade.semester not in semester_grades:
                        semester_grades[grade.semester] = []
                    semester_grades[grade.semester].append(grade)
                
                for semester in sorted(semester_grades.keys()):
                    f.write(f"{semester} 学期成绩:\n")
                    f.write("-" * 40 + "\n")
                    
                    semester_total_gp = 0
                    semester_total_credits = 0
                    
                    for grade in semester_grades[semester]:
                        # 查找课程信息
                        course = None
                        for c in self.courses:
                            if c.course_id == grade.course_id:
                                course = c
                                break
                        
                        course_name = course.course_name if course else "未知课程"
                        credits = course.credits if course else 0
                        
                        f.write(f"  {course_name} ({grade.course_id}): {grade.score:.1f}分 "
                               f"({grade.get_letter_grade()}) 绩点:{grade.get_grade_point():.1f} "
                               f"学分:{credits:.1f} [{grade.exam_type}]\n")
                        
                        if grade.exam_type == "期末考试" and course:
                            semester_total_gp += grade.get_grade_point() * credits
                            semester_total_credits += credits
                    
                    if semester_total_credits > 0:
                        semester_gpa = semester_total_gp / semester_total_credits
                        f.write(f"\n  {semester} 学期GPA: {semester_gpa:.3f}\n")
                    
                    f.write("\n")
                
                # 计算总GPA
                final_grades = [g for g in student_grades if g.exam_type == "期末考试"]
                if final_grades:
                    total_gp = 0
                    total_credits = 0
                    
                    for grade in final_grades:
                        course = None
                        for c in self.courses:
                            if c.course_id == grade.course_id:
                                course = c
                                break
                        
                        if course:
                            total_gp += grade.get_grade_point() * course.credits
                            total_credits += course.credits
                    
                    if total_credits > 0:
                        overall_gpa = total_gp / total_credits
                        f.write(f"总GPA: {overall_gpa:.3f}\n")
                        f.write(f"总学分: {total_credits:.1f}\n")
                
                f.write("=" * 60 + "\n")
            
            print(f"成绩报告已生成: {report_filename}")
            
        except Exception as e:
            print(f"生成报告时出错: {e}")
    
    def show_system_status(self):
        """显示系统状态"""
        print("\n=== 系统状态检查 ===")
        print("=" * 50)

        # 用户权限管理状态
        print("🔐 用户权限管理:")
        print("  ✅ 用户认证与登录")
        print("  ✅ 密码加密存储")
        print("  ✅ 角色-based访问控制(RBAC)")
        print("  ✅ 权限检查装饰器")
        print("  ✅ 用户管理功能")
        print("  ✅ 会话管理")
        print(f"  - 当前用户总数: {len(self.users)} 个")
        if self.current_user:
            print(f"  - 当前登录用户: {self.current_user.username} ({self.current_user.role})")
        else:
            print("  - 当前无用户登录")

        # 基础功能状态
        print("\n📋 基础功能:")
        print("  ✅ 学生信息管理 (增删改查)")
        print("  ✅ 课程信息管理 (增删改查)")
        print("  ✅ 成绩管理系统 (录入、查询、统计)")
        print("  ✅ GPA计算与排名")
        print("  ✅ 数据验证")
        print("  ✅ 表格显示")
        print("  ✅ 统计分析")
        print("  ✅ 高级查询")
        print("  ✅ 批量操作")
        print("  ✅ 数据备份恢复")
        print("  ✅ 成绩报告生成")
        
        # 图表功能状态
        print(f"\n📊 数据可视化:")
        if MATPLOTLIB_AVAILABLE:
            print("  ✅ 图表生成功能")
            print("    - 专业分布柱状图")
            print("    - 班级分布柱状图")
            print("    - 年龄分布折线图")
            print("    - 年龄分布柱状图")
            print("    - 综合统计图表")
        else:
            print("  ❌ 图表生成功能 (需要安装matplotlib)")
            print("    安装命令: pip install matplotlib")
        
        # Excel功能状态
        print(f"\n📈 Excel功能:")
        if OPENPYXL_AVAILABLE and PANDAS_AVAILABLE:
            print("  ✅ Excel导入导出功能")
            print("    - 导出到Excel文件")
            print("    - 从Excel文件导入")
        else:
            print("  ❌ Excel功能 (需要安装openpyxl和pandas)")
            print("    安装命令: pip install openpyxl pandas")
        
        # CSV功能状态
        print(f"\n📄 CSV功能:")
        if PANDAS_AVAILABLE:
            print("  ✅ CSV导入导出功能")
            print("    - 导出到CSV文件")
            print("    - 从CSV文件导入")
        else:
            print("  ❌ CSV功能 (需要安装pandas)")
            print("    安装命令: pip install pandas")
        
        # 数据统计
        print(f"\n📊 数据统计:")
        print(f"  - 当前学生总数: {len(self.students)} 人")
        print(f"  - 当前课程总数: {len(self.courses)} 门")
        print(f"  - 当前成绩记录: {len(self.grades)} 条")
        
        if self.students:
            ages = [s.age for s in self.students]
            majors = set(s.major for s in self.students)
            classes = set(s.class_name for s in self.students)
            print(f"  - 年龄范围: {min(ages)} - {max(ages)} 岁")
            print(f"  - 专业数量: {len(majors)} 个")
            print(f"  - 班级数量: {len(classes)} 个")
        
        if self.courses:
            total_credits = sum(c.credits for c in self.courses)
            print(f"  - 课程总学分: {total_credits:.1f}")
        
        if self.grades:
            semesters = set(g.semester for g in self.grades)
            exam_types = set(g.exam_type for g in self.grades)
            print(f"  - 涉及学期: {len(semesters)} 个")
            print(f"  - 考试类型: {len(exam_types)} 种")
        
        print("\n💡 提示:")
        print("  - 所有基础功能都可用")
        print("  - 如需使用高级功能，请安装相应的库")
        print("  - 系统会自动检测并禁用不可用的功能")
        
        print("=" * 50)
    
    def show_menu(self):
        """显示主菜单"""
        print("\n" + "="*50)
        print("           学生信息管理系统")
        print("           作者：方旺")
        print("           学号：20250101")
        print("           班级：23A")
        print("           专业：土木工程")
        print("           联系方式：18888888888")
        print("           邮箱：18888888888@qq.com")
        print("           地址：广东省广州市天河区")
        print("="*50)
        print("1. 添加学生信息")
        print("2. 删除学生信息")
        print("3. 修改学生信息")
        print("4. 查询学生信息")
        print("5. 数据统计分析")
        print("6. 高级查询")
        print("7. 数据导入导出")
        print("8. 批量操作")
        print("9. 课程管理")
        print("10. 成绩管理")
        print("11. 系统状态")
        print("12. 退出系统")
        print("="*50)
    
    def show_role_based_menu(self):
        """根据用户角色显示菜单"""
        print("\n" + "="*60)
        print("           学生信息管理系统")
        print("           作者：方旺")
        print("           学号：20250101")
        print("           班级：23A")
        print("           专业：土木工程")
        print("           联系方式：18888888888")
        print("           邮箱：18888888888@qq.com")
        print("           地址：广东省广州市天河区")
        print("="*60)
        print(f"当前用户: {self.current_user.username} (角色: {self.current_user.role})")
        print("="*60)

        if self.current_user.role == 'admin':
            print("1. 用户管理")
            print("2. 添加学生信息")
            print("3. 删除学生信息")
            print("4. 修改学生信息")
            print("5. 查询学生信息")
            print("6. 数据统计分析")
            print("7. 高级查询")
            print("8. 数据导入导出")
            print("9. 批量操作")
            print("10. 课程管理")
            print("11. 成绩管理")
            print("12. 系统状态")
            print("13. 登出")
            print("14. 退出系统")
        elif self.current_user.role == 'teacher':
            print("1. 查询学生信息")
            print("2. 数据统计分析")
            print("3. 高级查询")
            print("4. 课程管理")
            print("5. 成绩管理")
            print("6. 系统状态")
            print("7. 登出")
            print("8. 退出系统")
        elif self.current_user.role == 'student':
            print("1. 查看个人信息")
            print("2. 查询成绩")
            print("3. 计算GPA")
            print("4. 系统状态")
            print("5. 登出")
            print("6. 退出系统")
        print("="*60)

    def run(self):
        """运行主程序"""
        print("欢迎使用学生信息管理系统！")

        # 如果没有用户，创建默认管理员账户
        if not self.users:
            print("检测到系统首次运行，正在创建默认管理员账户...")
            admin_user = User("admin", User.hash_password("admin123"), "admin")
            self.users.append(admin_user)
            self.save_users()
            print("默认管理员账户已创建：")
            print("用户名: admin")
            print("密码: admin123")
            print("角色: admin")

        # 登录循环
        while not self.current_user:
            print("\n请选择操作:")
            print("1. 登录")
            print("2. 退出系统")
            choice = input("请选择 (1-2): ").strip()

            if choice == '1':
                if self.login():
                    break
            elif choice == '2':
                print("感谢使用学生信息管理系统，再见！")
                return
            else:
                print("无效选择！")

        # 主程序循环
        while True:
            self.show_role_based_menu()

            if self.current_user.role == 'admin':
                choice = input("请选择操作 (1-14): ").strip()
                if choice == '1':
                    self.user_management_menu()
                elif choice == '2':
                    self.add_student()
                elif choice == '3':
                    self.delete_student()
                elif choice == '4':
                    self.update_student()
                elif choice == '5':
                    self.query_students()
                elif choice == '6':
                    self.statistics_menu()
                elif choice == '7':
                    self.advanced_query()
                elif choice == '8':
                    self.import_export_menu()
                elif choice == '9':
                    self.batch_operations_menu()
                elif choice == '10':
                    self.course_management_menu()
                elif choice == '11':
                    self.grade_management_menu()
                elif choice == '12':
                    self.show_system_status()
                elif choice == '13':
                    self.logout()
                    if not self.current_user:
                        break
                elif choice == '14':
                    print("感谢使用学生信息管理系统，再见！")
                    break
                else:
                    print("无效选择，请重新输入！")

            elif self.current_user.role == 'teacher':
                choice = input("请选择操作 (1-8): ").strip()
                if choice == '1':
                    self.query_students()
                elif choice == '2':
                    self.statistics_menu()
                elif choice == '3':
                    self.advanced_query()
                elif choice == '4':
                    self.course_management_menu()
                elif choice == '5':
                    self.grade_management_menu()
                elif choice == '6':
                    self.show_system_status()
                elif choice == '7':
                    self.logout()
                    if not self.current_user:
                        break
                elif choice == '8':
                    print("感谢使用学生信息管理系统，再见！")
                    break
                else:
                    print("无效选择，请重新输入！")

            elif self.current_user.role == 'student':
                choice = input("请选择操作 (1-6): ").strip()
                if choice == '1':
                    self.view_personal_info()
                elif choice == '2':
                    self.query_grades_by_student()
                elif choice == '3':
                    self.calculate_student_gpa()
                elif choice == '4':
                    self.show_system_status()
                elif choice == '5':
                    self.logout()
                    if not self.current_user:
                        break
                elif choice == '6':
                    print("感谢使用学生信息管理系统，再见！")
                    break
                else:
                    print("无效选择，请重新输入！")

            if self.current_user:  # 如果还有用户登录，继续循环
                input("\n按回车键继续...")

def main():
    """主函数"""
    try:
        system = StudentManagementSystem()
        system.run()
    except KeyboardInterrupt:
        print("\n\n程序被用户中断")
    except Exception as e:
        print(f"程序运行出错: {e}")

if __name__ == "__main__":
    main()
